<?php
/***************************************************************************
 *   Copyright (C) 2007 by Andrea Blankenstijn, David Dieulivol            *
 *   darkan9el@gmail.com, daviddieulivol5@hotmail.com                      *
 *                                                                         *
 *   All rights reserved.                                                  *
 *   This work is released under the terms of the New BSD License.         *
 *   See LICENSE.BSD file for licensing details                            *
 ***************************************************************************/
/* * *
 * $Id: pdoProxy.class.php 50 2007-09-02 08:35:29Z DarkAn9el $
 * * */

/**
 * \class PdoProxy
 * \version $Revision: 50 $
 * \date $Date: 2007-09-02 08:35:29 +0000 (Sun, 02 Sep 2007) $
 * \author Andrea Blankenstijn
 * \brief Classe proxy à PDO
 * 
 * Cette classe transporte le préfixe des tables et apportes égallement des méthodes pour modifier à la volée
 * la requête SQL afin de s'adapter aux DBMS autres que MySQL. Testée avec MySQL, PostgreSQL et SQLite
 */
class PdoProxy
{
	private $dbh;       ///< instance de PDO
	private $prefix;    ///< préfixe des tables
	private $pdoDriver; ///< pilote de DBMS PDO utilisé
	private $sqlStr;    ///< chaîne de requête SQL à envoyer à PDO

	/**
	 * \brief Méthode de surcharge pour transmètre les requêtes à PDO
	 * 
	 * Cette méthode est appelée automatiquement lors d'un appel à une méthode
	 * non définie dans la classe. Si la méthode appelée est exec ou prepare, l'argument
	 * sera traité par parseSqlString puis transmis a la méthode de PDO correspondante.
	 * Une exception est lâchée si la méthode appelée est autre que exec ou prepare.
	 * 
	 * \param[in] $called méthode appelée
	 * \param[in] $args tableau d'arguments
	 * \return $exit retour de PDO::exec ou PDO::prepare 
	 */
	public function __call($called, $args)
	{
		switch($called)
		{
			case 'exec': case 'prepare': case 'query':
				$query = $this->parseSqlString($args[0]);
				$exit  = $this->dbh->$called($query);
			break;

			default:
				throw new Exception('PdoProxy: Erreur: cette méthode n\'existe pas', $exit = 1);
			break;
		}

		return $exit;
	}

	/**
	 * \brief Crée une instance de PdoProxy et de PDO
	 * 
	 * \param[in] $dsn chaîne DSN de connexion à la DB, tel que décris dans la documentation de PDO
	 * \param[in] $tablePrefix le prefixe à ajouter au nom des tables (optionnel)
	 * \param[in] $username nom d'utilisateur de connexion à la DB (si requis)
	 * \param[in] $password mot de passe de connexion à la DB (si requis)
	 * \param[in] $pdoOptionsArray tableau d'options à passer au constructeur de PDO
	 * 
	 * \return 0 aucune erreur
	 * \return 1 la tentative de connexion à la DB a lâchée une exception
	 */
	public function __construct($dsn, $tablePrefix = NULL, $username = NULL, $password = NULL, $pdoOptionsArray = NULL)
	{
		try
		{
			$this->dbh = new PDO($dsn, $username, $password, $pdoOptionsArray);
			$this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
		}
		catch (PDOException $e)
		{
			echo 'Erreur de connexion à la base de donnée : ', $e->getMessage();
			return 1;
		}

		$this->pdoDriver = $this->dbh->getAttribute(PDO::ATTR_DRIVER_NAME);
		$this->prefix = $tablePrefix;

		return 0;
	}

	/**
	 * \brief Accès à dbh, l'instance PDO
	 * \return $this->dbh PDO Object
	 */
	public function getDbh()
	{
		return $this->dbh;
	}

	/**
	 * \brief Accès à prefix, le prefixe des tables
	 * \return $this->prefix prefixe des tables
	 */
	public function getPrefix()
	{
		return $this->prefix;
	}

	/**
	 * \brief Traitement de syntaxe SQL
	 * 
	 * Lance une méthode de traitement de la syntaxe SQL
	 * selon la DBMS utilisée.
	 * 
	 * \return $this->sqlStr SQL traité
	 */
	private function parseSqlString($sqlStr)
	{
		$this->sqlStr = $sqlStr;

		switch($this->pdoDriver)
		{
			case 'pgsql':
				$this->sqlForPostgre();
			break;

			default:
			break;
		}

		return $this->sqlStr;
	}

	/**
	 * \brief Adapte la syntaxe SQL au spécifités de PostgreSQL
	 */
	private function sqlForPostgre()
	{
		// quotes MySQL → PostgreSQL
		$pattern     = '/`/';
		$replacement = '"';

		$this->sqlStr = preg_replace($pattern, $replacement, $this->sqlStr);
	}
}
?>